﻿#pragma once
#include "zyCtrol.h"
#include "zyEditBox.h"
#include "zyWindow.h"
#include "zyLmageList.h"


namespace BlackMoonUI {

	class zyListView : public  zyCtrol
	{
	public:
		struct 黑月超列信息 {
			std::wstring 标题; //@备注 本参数指定表项的标题文本(也即是第0列的标题)。
			int 图片索引; //图片索引用于指定“图片组”属性中的某张图片。索引值从 0 开始，-1 表示无图片。
			int 状态图片索引; //状态图片索引用于指定“状态图片组”属性中的某张图片。索引值从 0 开始，-1 表示无图片。
			LPARAM 表项数值=0; //该数值与指定表项相关联。
			int 缩进数目; //“缩进数目”仅在报表型列表框才有效，用作指定显示时在表项首部增加的空白数。
			std::vector<std::wstring>  列标题; //从第1列开始计起的列标题，多列请按列索引次序依次写到相应的数组成员中
			std::vector<int>  列图片索引; //从第1列开始计起，可以被省略。图片索引用于指定“图片组”属性中的某张图片。索引值从 0 开始，-1 表示无图片。如果本参数被省略，默认值为 -1 。
		};
	public:
		zyListView();
		~zyListView();
		
		static void  WINAPI zyListView_Destroy(zyObject* obj);
		static LRESULT WINAPI zyListView_WndProc(zyObject* obj, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL* bHandled);
		static LRESULT WINAPI zyListView_ChildWndProc(zyObject* obj, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL* bHandle);
		BOOL 创建(HWND 参数_父窗口, const std::wstring& 参数_标题 = L"", POINT 参数_位置 = POINT{ 0, 0 }, 
			POINT 参数_尺寸 = POINT{ 60, 120 },int 参数_ID = 0, int 参数_窗口风格 = 0, int 参数_扩展风格 = 0);
		BOOL 创建(zyWindow& 参数_父窗口, const std::wstring& 参数_标题 = L"", POINT 参数_位置 = POINT{ 0, 0 }, 
			POINT 参数_尺寸 = POINT{ 60, 120 },int 参数_ID = 0, int 参数_窗口风格 = 0, int 参数_扩展风格 = 0);
		int 插入列(int 参数_插入位置 = -1, const std::wstring& 参数_标题文本 = L"", int 参数_列宽 = -1, int 参数_对齐方式 = -1, 
			int 参数_图片索引 = -1, bool 参数_列图片是否居右 = false);
		int 取列数();
		int 取表项数();
		int 插入表项(int 参数_插入位置 = -1, const std::wstring& 参数_标题文本 = L"", int 参数_图片索引 = -1, 
			int 参数_状态图片索引 = -1, int 参数_缩进数目 = -1, LPARAM 参数_项目数值 = -1, int 参数_分组ID = -1);
		bool 置标题(int 参数_表项索引, int 参数_列索引 = 0, const std::wstring& 参数_欲置入标题 = L"");
		bool 绑定(HWND 参数_父窗口, int 参数_资源ID, bool 参数_使用默认字体);
		bool 绑定窗口句柄(HWND 参数_窗口句柄);
		//@备注 必须要启用Window通用组件6.0版。成功返回分组索引，失败返回-1。要使用分组功能要先调用"超级列表框.启用分组()"，然后在 插入表项 时指定分组ID
		int 插入分组(int 参数_插入位置 = -1, int 参数_分组ID = 1, const std::wstring& 参数_组头标题 = L"", const std::wstring& 参数_页脚标题 = L"", int 参数_对齐方式 = NULL, int 参数_状态 = NULL);
		bool 启用分组(bool 参数_是否启用);
		int 取表项分组ID(int 参数_表项索引);
		bool 置表项分组ID(int 参数_表项索引, int 参数_分组ID);
		std::wstring 取分组头标题(int 参数_分组ID);
		std::wstring 取分组页脚标题(int 参数_分组ID);
		int 取分组对齐方式(int 参数_分组ID);
		bool 置分组对齐方式(int 参数_分组ID, int 参数_对齐方式);
		bool 置分组头标题(int 参数_分组ID, const std::wstring& 参数_标题);
		bool 置分组页脚标题(int 参数_分组ID, const std::wstring& 参数_标题);
		int 取分组状态(int 参数_分组ID);
		bool 置分组状态(int 参数_分组ID, int 参数_状态);
		int 取分组ID(int 参数_分组索引);
		int 取分组数() { return (int)sendMsg(LVM_GETGROUPCOUNT, 0, 0); }
		//@备注 返回值：整型【小于0表示 分组ID1< 分组ID2；大于0表示 分组ID1> 分组ID2；0相等】 (整型 分组ID1,整型 分组ID2,整型 用户数据)
		bool 排序分组(void* 参数_回调函数, LPARAM 参数_用户数据);
		std::wstring 取标题(int 参数_表项索引, int 参数_列索引, int 参数_长度 = 260);
		//@备注 取回指定表项或子项的图片索引，图片索引指向图片组属性中的某一图片，从 0 开始，-1 表示无图片
		int 取图片(int 参数_表项索引, int 参数_列索引 = 0);
		//@备注 取回指定表项的当前状态图片索引，图片索引指向状态图片组属性中的某一图片，从 0 开始，-1 表示无图片。如果有"超列扩展_显示检查框"风格，返回值是当前检查框的选中状态，1表示被选中，0表示未选中。
		int 取状态图片(int 参数_表项索引);
		int 取缩进数目(int 参数_表项索引);
		LPARAM 取表项数值(int 参数_表项索引);
		int 取表项状态(int 参数_表项索引);
		bool 置表项状态(int 参数_表项索引, int 参数_添加的状态, int 参数_移除的状态);
		bool 置图片(int 参数_表项索引, int 参数_列索引, int 参数_图片索引 = -1);
		bool 置状态图片(int 参数_表项索引, int 参数_状态图片索引 = -1);
		bool 置缩进数目(int 参数_表项索引, int 参数_缩进数目 = 0);
		bool 置表项数值(int 参数_表项索引, LPARAM 参数_表项数值 = 0);
		int 取被选择表项(std::vector<int>& 参数_被选择表项数组);
		int 取被选中表项(std::vector<int>& 参数_被选中表项数组);
		int 取已选择表项数() { return (int)sendMsg(LVM_GETSELECTEDCOUNT, 0, 0); }
		bool 是否被选择(int 参数_表项索引) { return sendMsg(LVM_GETITEMSTATE, 参数_表项索引, LVIS_SELECTED) == LVIS_SELECTED; }
		int 取现行选中项() { return (int)sendMsg(LVM_GETNEXTITEM, -1, LVNI_SELECTED); }
		bool 置现行选中项(int 参数_表项索引);
		bool 选择表项(int 参数_表项索引);
		bool 取消表项选择(int 参数_表项索引);
		//@备注 参数一：lParam1(表项数值1)整数型，参数二：lParam2(表项数值2)整数型，参数三：lParamSort(参数_排序参数)整数型。如果返回参数一小于参数二为由小到大排序，如果返回参数二小于参数一为由大到小排序。
		bool 排序表项(int 参数_排序参数, void* 参数_排序子程序) {
			return sendMsg(LVM_SORTITEMS, 参数_排序参数, (LPARAM)参数_排序子程序) != 0;
		}
		int 删除表项(int 参数_表项索引) { return (int)sendMsg(LVM_DELETEITEM, 参数_表项索引, 0); }
		int 删除列(int 参数_列索引) { return (int)sendMsg(LVM_DELETECOLUMN, 参数_列索引, 0); }
		int 全部删除() { return (int)sendMsg(LVM_DELETEALLITEMS, 0, 0); }
		int 查找表项(const std::wstring& 参数_标题文本, int 参数_起始位置 = -1, bool 参数_是否精确匹配 = true, bool 参数_查找不到是否从头开始 = true);
		int 查找表项数值(LPARAM 参数_表项数值, int 参数_起始位置 = -1, bool 参数_查找不到是否从头开始 = true);
		bool 保证显示(int 参数_表项索引, bool 参数_是否保证显示 = true);
		bool 自动排列(bool 参数_对齐到网格);
		std::wstring 取列标题(int 参数_列索引);
		int 取列对齐方式(int 参数_列索引);
		bool 置列对齐方式(int 参数_列索引, int 参数_对齐方式);
		int 取列宽(int 参数_列索引);
		int 取现行选择列();
		void 置现行选择列(int 参数_列索引);
		int 取列图片(int 参数_列索引);
		bool 图片是否居右(int 参数_列索引);
		bool 置列标题(int 参数_列索引, const std::wstring& 参数_标题文本);
		bool 置列宽(int 参数_列索引, int 参数_欲置入宽度 = -1);
		bool 置列图片(int 参数_列索引, int 参数_图片索引 = -1);
		bool 取列矩形(int 参数_表项索引, int 参数_列索引, RECT& 参数_矩形结构, int 参数_取出类型);
		void 进入编辑(int 参数_表项索引);
		//@备注 会发送"事件_结束编辑"
		void 取消编辑() { sendMsg(LVM_CANCELEDITLABEL, 0, 0); }
		黑月超列信息 取项目数据(int 参数_表项索引);
		int 取所有项目数据(std::vector<黑月超列信息>& 参数_列表框信息数组);
		void 高速插入表项(int 参数_插入位置, std::vector<黑月超列信息>& 参数_列表框信息数组, int 参数_排序方式, int 参数_列索引 = 0, bool 参数_逆向 = false);
		bool 置表项(const std::vector<BYTE>& tableData);
		std::vector<BYTE> 取表项();
		void 刷新显示();
		int 取可见第一项();
		int 取可见表项数();
		int 取编辑框句柄();
		void 取表项间距(short& 参数_水平间距, short& 参数_垂直间距, bool 参数_列表框类型);
		int 取坐标表项索引(int 参数_横坐标, int 参数_纵坐标, int& 参数_表项索引, int& 参数_列索引, int& 参数_分组ID);
		bool 取表项位置(int 参数_表项索引, POINT& 参数_坐标位置);
		bool 取表项矩形(int 参数_表项索引, RECT& 参数_矩形, int 参数_取出类型);
		zyLmageList* 取图片组(int 参数_类型);
		void 置图片组(zyLmageList& 参数_图片组, int 参数_类型);
		zyLmageList 创建拖放图片组(int 参数_表项索引, POINT& 参数_参考坐标);
		bool 滚动列表框(int 参数_水平位置, int 参数_垂直位置);
		int 添加超列扩展风格(int 参数_扩展风格);
		int 取超列扩展风格();
		int 移除超列扩展风格(int 参数_扩展风格);
		int 文本色(int 参数_文本色 = 0);
		int 文本背景色(int 参数_文本背景颜色 = 0);
		int 背景色(int 参数_背景色, bool 参数_是否立即重画);
		int 取显示类型();
		bool 置显示类型(int 参数_显示类型);
		zyEditBox* 取编辑框();
		int 取表项索引(int 参数_标志, int 参数_起始索引 = -1);
		void 置表项坐标(int 参数_表项索引, int 参数_X, int 参数_Y);
		POINT 取表项坐标(int 参数_表项索引);
		int 置大图标间距(int 参数_水平间距, int 参数_垂直间距);
		//@备注 函数 整型 OnItemChange(HWND hWnd,整型 表项索引,整型 项目数值)
		void 事件_当前表项被改变(TRegEvent* 参数_事件指针) ; 
		//@备注 返回值：整型【0允许选择，1禁止选择】 函数 整型 OnHotTrack(HWND hWnd,整型 表项索引,整型 列索引)
		void 事件_表项跟踪(TRegEvent* 参数_事件指针) ; 
		//@备注 函数 整型 OnColumnClick(HWND hWnd,整型 列索引)
		void 事件_表头被单击(TRegEvent* 参数_事件指针) ; 
		//@备注 函数 整型 OnItemActivate(HWND hWnd,整型 表项索引,整型 列索引)
		void 事件_表项被激活(TRegEvent* 参数_事件指针) ; 
		//@备注 返回值：整型【0允许编辑，1禁止编辑】函数 整型 OnBeginEdit(HWND hWnd,整型 表项索引)
		void 事件_开始编辑(TRegEvent* 参数_事件指针) ; 
		//@备注 返回值：整型【0允许编辑，1禁止编辑】函数 整型 OnEndEdit(HWND hWnd,整型 表项索引,整型 标题[Unicode文本指针-1])
		void 事件_结束编辑(TRegEvent* 参数_事件指针) ; 
		//@备注 函数 整型 OnClick(HWND hWnd,整型 表项索引,整型 列索引,整型 X,整型 Y,整型 功能键状态[1、Alt；2、Ctrl；4、Shift-1])
		void 事件_左键单击表项(TRegEvent* 参数_事件指针) ; 
		//@备注 返回值：整型【0默认处理，1阻止默认处理】 函数 整型 OnRClick(HWND hWnd,整型 表项索引,整型 列索引,整型 X,整型 Y,整型 功能键状态[1、Alt；2、Ctrl；4、Shift-1])
		void 事件_右键单击表项(TRegEvent* 参数_事件指针) ; 
		//@备注 函数 整型 OnDBClick(HWND hWnd,整型 表项索引,整型 列索引,整型 X,整型 Y,整型 功能键状态[1、Alt；2、Ctrl；4、Shift-1])
		void 事件_双击表项(TRegEvent* 参数_事件指针) ; 
		//@备注 函数 整型 OnCheckChange(HWND hWnd,整型 表项索引,整型 检查框状态
		void 事件_检查框状态被改变(TRegEvent* 参数_事件指针) ; 
		//@备注 函数 整型 OnBeginDrag(HWND hWnd,整型 表项索引)
		void 事件_开始拖放(TRegEvent* 参数_事件指针) ; 
	protected:
		void OnNCDestroy();
		//void _快速排序(std::vector<黑月超列信息>& 参数_列表框信息数组, int 参数_左边 = 1, int 参数_右边 = 0, int 参数_排序方式 = -1, int 参数_列索引 = 0, bool 参数_逆向 = false);
		void _快速排序(std::vector<黑月超列信息>& 参数_列表框信息数组, int 参数_左边, int 参数_右边, int 参数_排序方式, int 参数_列索引, bool 参数_逆向);
		void SetData(std::vector<BYTE>& buffer, size_t& offset, const void* data, size_t size);
	};

}

